import { Injectable } from '@nestjs/common';
import { AppService } from 'src/app.service';
import { bytesToSize } from 'src/utils';
const os = require('node:os');
const { exec } = require('child_process');
const path = require('path');

@Injectable()
export class ServerService {
  constructor(
    private readonly appService:AppService
  ) {}

  async serverInfo() {
    const cpu = this.getCpuInfo();
    const mem = this.getMemInfo();
    const sys = {
      computerName: os.hostname(),
      computerIp: this.getServerIP(),
      userDir: path.resolve(__dirname, '..', '..', '..', '..'),
      osName: os.platform(),
      osArch: os.arch(),
      startTime: this.appService.getStartTime()
    };
    const disks = await this.getDisks();
    return {
      cpu,
      mem,
      sys,
      disks,
    };
  }

  // 获取CPU信息
  getCpuInfo() {
    const cpus = os.cpus();
    const cpuInfo = cpus.reduce(
      (info, cpu) => {
        info.cpuNum += 1;
        info.userTimes += cpu.times.user;
        info.sysTimes += cpu.times.sys;
        info.idleTimes += cpu.times.idle;
        info.totalTimes += cpu.times.user + cpu.times.sys + cpu.times.idle;
        return info; // 确保返回info对象以便在下次迭代中使用
      },
      {
        userTimes: 0,
        sysTimes: 0,
        idleTimes: 0,
        totalTimes: 0,
        cpuNum: 0,
      },
    );
    return {
      cpuNum: cpuInfo.cpuNum, // cpu核心数
      total: cpuInfo.totalTimes, // 瞬时快照所用的总时间
      sys: ((cpuInfo.sysTimes / cpuInfo.totalTimes) * 100).toFixed(2), // 系统利用率
      used: ((cpuInfo.userTimes / cpuInfo.totalTimes) * 100).toFixed(2), // 用户使用率
      free: ((cpuInfo.idleTimes / cpuInfo.totalTimes) * 100).toFixed(2), // 当前空闲率
    };
  }

  // 获取内存信息
  getMemInfo() {
    // 获取总内存
    const totalMemory = os.totalmem();
    // 获取空闲内存
    const freeMemory = os.freemem();
    // 已用内存 = 总内存 - 空闲内存
    const usedMemory = totalMemory - freeMemory;
    // 使用率 = 1 - 空闲内存 / 总内存
    const memoryUsagePercentage = (
      ((totalMemory - freeMemory) / totalMemory) *
      100
    ).toFixed(2);
    return {
      total: bytesToSize(totalMemory),
      used: bytesToSize(usedMemory),
      free: bytesToSize(freeMemory),
      usage: memoryUsagePercentage,
    };
  }

  // 获取服务器IP地址
  getServerIP() {
    const nets = os.networkInterfaces();
    for (const name of Object.keys(nets)) {
      for (const net of nets[name]) {
        // 选择外部可访问的IPv4地址
        if (net.family === 'IPv4' && !net.internal) {
          return net.address;
        }
      }
    }
  }

  // 获取系统磁盘信息
  async getDisks() {
    const platform = os.platform();
    return new Promise((resolve, reject) => {
      // macOS/Linux
      if (['darwin', 'linux'].includes(platform)) {
        exec('df -h', (error, stdout, stderr) => {
          if (error) {
            resolve(null);
            return;
          }
          if (stderr) {
            resolve(null);
            return;
          }
          const lines = stdout.split('\n').slice(1); // 跳过标题行
          const disks = lines.map((line) => {
            const parts = line.trim().split(/\s+/); // 使用空白字符分割
            return {
              filesystem: parts[0],
              size: parts[1],
              used: parts[2],
              avail: parts[3],
              percent: parts[4],
              mounted: parts[5],
              // 如果需要更多信息，可以继续添加
            };
          });

          resolve(disks);
        });
      } 
      // windows
      else if (platform === 'win32') {
        exec(
          'wmic logicaldisk get Name,Freespace,Size,FileSystem,DriveType',
          (error, stdout, stderr) => {
            if (error) {
              resolve(null);
              return;
            }
            if (stderr) {
              resolve(null);
              return;
            }
            // 获取返回的字段名称数组（有时可能并不是按照wmic命令查找的顺序）
            let units = stdout.split('\r\n').slice(0, 1)[0].trim().split(/\s+/);
            // 获取数据行
            const lines = stdout.split('\r\n').slice(1);
            const disks = lines
              .filter((line) => line.trim() !== '')
              .map((line) => {
                const parts = line.trim().split(/\s+/);
                return {
                  [units[0]]: parts[0],
                  [units[1]]: parts[1],
                  [units[2]]: parts[2],
                  [units[3]]: parts[3],
                  [units[4]]: parts[4],
                };
              });

            resolve(disks);
          },
        );
      } else {
        console.log(`未知的操作系统: ${platform}`);
        resolve(null);
      }
    });
  }
}
